package com.hx.demo.config;

import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import com.hx.demo.filter.VerificationCodeFilter;
import com.hx.demo.handle.MyFailSecurityHandle;
import com.hx.demo.handle.MyLogoutSuccessHandler;
import com.hx.demo.handle.MySuccessSecurityHandle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 注解都是有组合性
 * @Bean 两种  1类 bean ；@Component @Service  @Re。。。
 *             2 放在方法上面 @Bean，一定要注意一点，类一定要被扫描
 */
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MySuccessSecurityHandle mySuccessSecurityHandle;

    @Autowired
    private MyFailSecurityHandle myFailSecurityHandle;

    @Autowired
    private MyLogoutSuccessHandler myLogoutSuccessHandler;



    @Override
    protected void configure(HttpSecurity http) throws Exception {

                http
                //关闭csrf 跨站拦截
                .csrf().disable()
                .authorizeRequests()
                //静态资源不需要授权
                // ** 匹配所有的层级   /user/sdfas/sadfads/fasd/fas/xxx.jpg
                // * 通配符
                //ANT模式使用？匹配任意单个字符，使用*
                        //匹配0或任意数量的字符，使用**匹配0或者更多的目录。
                .antMatchers(HttpMethod.GET,
                        "/**/*.jpg",
                        "/**/*.png",
                        "/**/*.js",
                        "/**/*.css").permitAll()
                //常见的登录，注册，修改密码，这些也是不需要用户授权
                .antMatchers("/toLogin","/login","/loginBody").permitAll()
                //后台所有的请求，都需要用户登录，才能访问 admin 最大  user 一般
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/app/**").hasRole("APP")
                .antMatchers("/user/**").permitAll()
                        .antMatchers("/captcha.jpg").permitAll()
                //所有其他的请求都要授权
                .anyRequest().authenticated()
                .and()
                .formLogin()
                //设置登录页面
                .loginPage("/toLogin")
                //设置表单请求的路径
                .loginProcessingUrl("/login")
                //登录成功后执行请求
                .successHandler(mySuccessSecurityHandle)
                //登录失败后执行的请求
                .failureHandler(myFailSecurityHandle);

        //将过滤器添加在UsernamePasswordAuthenticationFilter之前
        http.addFilterBefore(new VerificationCodeFilter(), UsernamePasswordAuthenticationFilter.class);

        http.logout()
                //指定接受注销请求的路径
                .logoutUrl("/logout")
                //注销成功，重定向到该路径下
                .logoutSuccessUrl("/toLogin")
                //注册成功之后处理方式
                .logoutSuccessHandler(myLogoutSuccessHandler)
                //使该用户的HttpSession失效
                .invalidateHttpSession(true)
                //注销成功，删除指定cookie
                .deleteCookies("remember-me");
    }


//    @Bean
//    public UserDetailsService userDetailsService(){
//        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
//        manager.createUser(User.withUsername("admin").password("123456").roles("ADMIN","APP").build());
//        manager.createUser(User.withUsername("app").password("123456").roles("APP").build());
//        return manager;
//    }


    @Bean
    public static PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    @Bean
    public Producer kaptcha() {
        //配置图形验证码的基本参数
        Properties properties = new Properties();
        //图片宽度
        properties.setProperty("kaptcha.image.width", "150");
        //图片长度
        properties.setProperty("kaptcha.image.height", "50");
        //字符集
        properties.setProperty("kaptcha.textproducer.char.string", "0123456789");
        //字符长度
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        Config config = new Config(properties);
        //使用默认的图形验证码实现，也可以自定义
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}
